import Vue from 'vue'


// 重写自己的call、apply和bind方法 ==>js中是在Function.prototype上边写的方法，但是百度搜的在vue项目中是用Vue.prototype；不清楚到底是咋弄的！！！！！！！！
// call方法
Vue.prototype.myCall = function (context) {
  if (typeof this !== 'function') {
    throw new TypeError('Not a Function')
  }
  // 不传参默认为window
  context = context || window
  // 保存this
  context.fn = this
  // 保存参数  ==> Array.from把维数组对象转化为数组
  let args = Array.from(arguments).slice(1)   
  // 调用参数
  let result = context.fn(...args)
  delete context.fn
  return result
}
// apply方法
Vue.prototype.myApply = function (context) {
  // 判断this是不是函数
  if (typeof this !== 'function') {
    throw new TypeError('Not a Function')
  }
  let result
  // 不传参默认是window
  context = context || window
  // 保存this
  context.fn = this
  // 判断是否传入参数
  if (arguments[1]) {
    result = context.fn(...arguments[1])
  } else {
    result = context.fn()
  }
  delete context.fn
  return  result
}
// bind方法
Function.prototype.myBind = function(context){
  // 判断是否是一个函数
  if(typeof this !== 'function') {
    throw new TypeError('Not a Function')
  }
  // 保存调用bind的函数
  const _this = this 
  // 保存参数
  const args = Array.prototype.slice.call(arguments,1)
  // 返回一个函数
  return function F () {
    // 判断是不是new出来的
    if(this instanceof F) {
      // 如果是new出来的
      // 返回一个空对象，且使创建出来的实例的__proto__指向_this的prototype，且完成函数柯里化
      return new _this(...args,...arguments)
    }else{
      // 如果不是new出来的改变this指向，且完成函数柯里化
      return _this.apply(context,args.concat(...arguments))
    }
  } 
}
// ----------------------------------------实现简单Promise----------------------------------------
class MyPromise{
  constructor(executor){
    // 规定状态
    this.state = 'pending'
    // 保存"resolve(res)"的res值
    this.value = undefined
    // 保存"resolve(res)"的err值
    this.reason = undefined
    // 成功存放的数组
    this.successCB = []
    // 失败存放的数组
    this.failCB = []
    let resolve = (value) => {
      if(this.state === 'pending'){
        this.state = 'fulfilled'
        this.value = value
        this.successCB.forEach(f => f())
      }
    }
    let reject = (reason) => {
      if(this.state === 'pending'){
        this.state = 'rejected'
        this.value = value
        this.failCB.forEach(f => f())
      }
    }
    try {
      executor(resolve, reject)
    } catch (error) {
      // 若出错，直接调用reject
      reject(error)
    }
  }
  then(onFulfilled, onRejected){
    if(this.state === 'fulfilled'){
      onFulfilled(this.value)
    }
    if(this.state === 'rejected'){
      onRejected(this.value)
    }
    if(this.state === 'pending'){
      this.successCB.push(() => {
        onFulfilled(this.value)
      })
      this.failCB.push(() => {
        onRejected(this.reason)
      })
    }
  }
}
Promise.all = function(promise){
  let list = []
  let count = 0
  function handle(i, data) {
    list[i] = data
    count++
    if(count == promise.length){
      resolve(list)
    }
  }
  return Promise((resolve, reject) => {
    for(let i =0; i < promise.length; i++){
      promise[i].then(res => {
        handle(i, res)
      }, err => reject(err))
    }
  })
}